package edu.scau.divineplace.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import edu.scau.divineplace.entity.dos.ContentBasicInformationDO;
import edu.scau.divineplace.entity.dos.ContentRoleRelationDO;
import edu.scau.divineplace.entity.dos.RoleCvRelationDO;
import edu.scau.divineplace.entity.dos.RoleTruthDO;
import edu.scau.divineplace.entity.enums.ContentTypeEnum;
import edu.scau.divineplace.entity.enums.RoleTruthEnum;
import edu.scau.divineplace.entity.enums.RoleTypeEnum;
import edu.scau.divineplace.entity.query.PageQuery;
import edu.scau.divineplace.entity.vo.role.*;
import edu.scau.divineplace.mapper.RoleServiceMapper;
import edu.scau.divineplace.util.PageQueryUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: x1aolone
 * @Date: 2020/12/11 15:48
 */
@Service
public class RoleService {

    @Autowired
    private ImportMapperService importMapperService;

    @Autowired
    private RoleServiceMapper roleServiceMapper;

    /**
     * 通过内容id获取内容的角色列表
     * @param contentId
     * @return
     */
    public List<RoleVO> getRoleList(Long contentId){
        List<RoleVO> listVOS = Lists.newArrayList();
        // 从content_role_relation中type=1的roleId、roleDetail
        // 然后根据id去content basic info中找到这个人的信息
        // cv信息，通过role_cv_relation找到cv的id，再去content basic info中找到这个cv的信息
        LambdaQueryWrapper<ContentRoleRelationDO> relationQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                .eq(ContentRoleRelationDO::getRoleType, RoleTypeEnum.PART.getType())
                .eq(ContentRoleRelationDO::getContentId, contentId);
        List<ContentRoleRelationDO> realtionDOs = importMapperService.contentRoleRelationMapper.selectList(relationQuery);
        // 遍历所有的角色
        for (ContentRoleRelationDO roleRealtionDO : realtionDOs) {
            // 获取角色的信息
            ContentBasicInformationDO basicInfoDO = importMapperService.contentBasicInformationMapper.selectById(roleRealtionDO.getRoleId());
            List<ContentBasicInformationDO> cvRolesInfo = new ArrayList<>();
            // 获取角色cv们的关系
            LambdaQueryWrapper<RoleCvRelationDO> cvRelationQuery = Wrappers.<RoleCvRelationDO>lambdaQuery()
                    .eq(RoleCvRelationDO::getRoleId, roleRealtionDO.getRoleId())
                    .eq(RoleCvRelationDO::getContentId, contentId);
            List<RoleCvRelationDO> cvRelationDOS = importMapperService.roleCvRelationMapper.selectList(cvRelationQuery);
            // 获取每一个cv的信息
            cvRelationDOS.forEach(x -> cvRolesInfo.add(importMapperService.contentBasicInformationMapper.selectById(x.getCvId())));
            RoleVO VO = RoleVO.builder()
                    .roleTypeDetail(roleRealtionDO.getRoleTypeDetail())
                    .roleInfo(basicInfoDO)
                    .cvRolesInfo(cvRolesInfo)
                    .build();
            listVOS.add(VO);
        }
        return listVOS;
    }

    /**
     * 通过角色id获取角色的真实性
     * @param roleId
     * @return
     */
    public Boolean judgeRoleTruth (Long roleId) {
        RoleTruthEnum roleTruth = getRoleTruth(roleId);
        return roleTruth == RoleTruthEnum.REAL;
    }

    public RoleTruthEnum getRoleTruth (Long roleId) {
        LambdaQueryWrapper<RoleTruthDO> query = Wrappers.<RoleTruthDO>lambdaQuery()
                .eq(RoleTruthDO::getRoleId, roleId)
                .last(" limit 1");
        RoleTruthDO DO = importMapperService.roleTruthMapper.selectOne(query);
        Preconditions.checkNotNull(DO);
        return DO.getRoleTruth();
    }


    /**
     * 通过虚拟角色id获取角色出演的内容
     * @param roleId
     * @param currentPage
     * @param pageSize
     * @return
     */
    public List<PerformVO> listVirtualPerform(Long roleId, Integer currentPage, Integer pageSize){
        if (currentPage == null) {
            currentPage = -1;
        }
        if (pageSize == null) {
            pageSize = -1;
        }
        List<PerformVO> VOS = Lists.newArrayList();
        // 先找到角色的类型和出演的内容id
        Page<ContentRoleRelationDO> relationPage = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<ContentRoleRelationDO> contentRoleQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                .eq(ContentRoleRelationDO::getRoleId, roleId)
                .eq(ContentRoleRelationDO::getRoleType, RoleTypeEnum.PART.getType())
                .orderByDesc(ContentRoleRelationDO::getUpdateTime)
                .orderByDesc(ContentRoleRelationDO::getCreateTime);
        relationPage = importMapperService.contentRoleRelationMapper.selectPage(relationPage, contentRoleQuery);
        for (ContentRoleRelationDO contentRoleRelationDO : relationPage.getRecords()) {
            Long contentId = contentRoleRelationDO.getContentId();
            // 获取出演的内容信息
            ContentBasicInformationDO contentInfo = importMapperService.contentBasicInformationMapper.selectById(contentId);
            // 获取角色在该内容中的cvId，可能角色有多个CV，也可能没有CV（比如漫画）
            LambdaQueryWrapper<RoleCvRelationDO> roleCvQuery = Wrappers.<RoleCvRelationDO>lambdaQuery()
                    .eq(RoleCvRelationDO::getRoleId, roleId)
                    .eq(RoleCvRelationDO::getContentId,contentId);
            List<RoleCvRelationDO> roleCvDOS = importMapperService.roleCvRelationMapper.selectList(roleCvQuery);
            List<ContentBasicInformationDO> cvInfos = null;
            if (!roleCvDOS.isEmpty()) {
                List<Long> cvIds = roleCvDOS.stream().map(RoleCvRelationDO::getCvId).collect(Collectors.toList());
                cvInfos = importMapperService.contentBasicInformationMapper.selectBatchIds(cvIds);
            }
            PerformVO VO = PerformVO.builder()
                    .contentInfo(contentInfo)
                    .roleTypeDetail(contentRoleRelationDO.getRoleTypeDetail())
                    .cvRolesInfo(cvInfos)
                    .build();
            VOS.add(VO);
        }
        return VOS;
    }


    /**
     * 通过真实角色id获取角色最近担任cv的内容，支持分页
     * @param cvId
     * @param currentPage
     * @param pageSize
     * @return
     */
    public List<CVContentRoleVO> listRealRecentCVRole(Long cvId, Integer currentPage, Integer pageSize){
        if (currentPage == null) {
            currentPage = -1;
        }
        if (pageSize == null) {
            pageSize = -1;
        }
        // 需要内容信息、角色信息、角色类型，同一个声优可能担任一个角色的多个内容
        List<CVContentRoleVO> VOS = Lists.newArrayList();
        // 先从role_cv_realtion里找到cvId=roleId的内容id和角色id
        Page<RoleCvRelationDO> relationPage = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<RoleCvRelationDO> roleCVQuery = Wrappers.<RoleCvRelationDO>lambdaQuery()
                .eq(RoleCvRelationDO::getCvId, cvId)
                .orderByDesc(RoleCvRelationDO::getRoleId)
                .orderByDesc(RoleCvRelationDO::getUpdateTime)
                .orderByDesc(RoleCvRelationDO::getCreateTime);
        relationPage = importMapperService.roleCvRelationMapper.selectPage(relationPage, roleCVQuery);
        List<RoleContentInfoVO> contentInfos = null;
        Long lastRoleId = null;
        // 从content_basic_info里找到内容的信息和角色的信息
        // relationPage通过角色id排序，同一个角色是连在一起的，把同一个roleId的不同内容都放在一起
        for (RoleCvRelationDO roleCvRelationDO : relationPage.getRecords()) {
            Long contentId = roleCvRelationDO.getContentId();
            Long roleId = roleCvRelationDO.getRoleId();
            // 获取内容信息
            ContentBasicInformationDO contentInfoDO =
                    importMapperService.contentBasicInformationMapper.selectById(roleCvRelationDO.getContentId());
            // 获取这个角色的人物类型详情，主角配角
            LambdaQueryWrapper<ContentRoleRelationDO> roleTypeDetailQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                    .eq(ContentRoleRelationDO::getRoleId, roleId)
                    .eq(ContentRoleRelationDO::getContentId,contentId)
                    .eq(ContentRoleRelationDO::getRoleType,RoleTypeEnum.PART.getType())
                    .last(" limit 1");
            ContentRoleRelationDO contentRoleRelationDO = importMapperService.contentRoleRelationMapper.selectOne(roleTypeDetailQuery);
            String RoleTypeDetail = contentRoleRelationDO.getRoleTypeDetail();
            RoleContentInfoVO contentInfo = RoleContentInfoVO.builder()
                    .contentInfo(contentInfoDO)
                    .roleTypeDetail(RoleTypeDetail)
                    .build();
            // lastRoleId为null时也为false，两个值不等时也为false
            if (!roleId.equals(lastRoleId)) {
                lastRoleId = roleId;
                // 不是同一个角色，查一下角色信息
                ContentBasicInformationDO roleInfo =
                        importMapperService.contentBasicInformationMapper.selectById(roleCvRelationDO.getRoleId());
                // 重新开始内容清单
                contentInfos = Lists.newArrayList();
                CVContentRoleVO VO = CVContentRoleVO.builder()
                        .roleInfo(roleInfo)
                        .contentInfos(contentInfos)
                        .build();
                VOS.add(VO);
            }
            // 如果是新的角色，要等新建List以后才能放进去
            contentInfos.add(contentInfo);
        }
        return VOS;
    }


    /**
     * 通过内容id获取内容的制作人，支持完美分页
     * @param contentId
     * @param currentPage
     * @param pageSize
     * @return
     */
    public List<ProducerVO> listProducer(Long contentId, Integer currentPage, Integer pageSize){
        if (currentPage == null) {
            currentPage = -1;
        }
        if (pageSize == null) {
            pageSize = -1;
        }
        // 为了防止分页出问题，查两次，第一次把roleId拿出来，第二次通过rid查这个人的作用List
        List<ProducerVO> VOS = Lists.newArrayList();
        Page<ContentRoleRelationDO> relationPage = new Page<>(currentPage, pageSize);
        LambdaQueryWrapper<ContentRoleRelationDO> relationQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                .eq(ContentRoleRelationDO::getContentId, contentId)
                .eq(ContentRoleRelationDO::getRoleType, RoleTypeEnum.PRODUCER)
                // RoleId去重
                .groupBy(ContentRoleRelationDO::getRoleId)
                .select(ContentRoleRelationDO::getRoleId);
        Page<ContentRoleRelationDO> page = importMapperService.contentRoleRelationMapper.selectPage(relationPage, relationQuery);
        for (ContentRoleRelationDO relationDO : page.getRecords()) {
            Long roleId = relationDO.getRoleId();
            // 通过RoleId去获取人物的具体作用
            LambdaQueryWrapper<ContentRoleRelationDO> roleTypeDetailQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                    .eq(ContentRoleRelationDO::getContentId, contentId)
                    .eq(ContentRoleRelationDO::getRoleId, roleId)
                    .eq(ContentRoleRelationDO::getRoleType, RoleTypeEnum.PRODUCER)
                    // RoleTypeDetail去重
                    .groupBy(ContentRoleRelationDO::getRoleTypeDetail)
                    .select(ContentRoleRelationDO::getRoleTypeDetail);
            List<ContentRoleRelationDO> roleTypeDetailDOS = importMapperService.contentRoleRelationMapper.selectList(roleTypeDetailQuery);
            List<String> roleTypeDetails = roleTypeDetailDOS.stream().map(ContentRoleRelationDO::getRoleTypeDetail).collect(Collectors.toList());
            // 获取人物信息
            LambdaQueryWrapper<ContentBasicInformationDO> roleQuery = Wrappers.<ContentBasicInformationDO>lambdaQuery()
                    .eq(ContentBasicInformationDO::getId, roleId)
                    .eq(ContentBasicInformationDO::getType, ContentTypeEnum.ROLE)
                    .last("limit 1");
            ContentBasicInformationDO roleInfoDO = importMapperService.contentBasicInformationMapper.selectOne(roleQuery);
            ProducerVO VO = ProducerVO.builder()
                    .roleInfo(roleInfoDO)
                    .roleTypeDetails(roleTypeDetails)
                    .build();
            VOS.add(VO);
        }
        return VOS;
    }

    /**
     * 通过获取最近更新的人物，完美分页
     * @param pageQuery
     * @return
     */
    public List<RoleSimplyInfoVO> listRecentRole(PageQuery pageQuery){
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        Page<RoleSimplyInfoVO> contentPage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        List<RoleSimplyInfoVO> VOS = roleServiceMapper
                .selectRecentRole(contentPage, ContentTypeEnum.ROLE.getType())
                .getRecords();
        return VOS;
    }

    /**
     * 通过获取最近更新的人物，完美分页
     * @param pageQuery
     * @return
     */
    public List<RoleSimplyInfoVO> listRankRole(PageQuery pageQuery){
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        Page<RoleSimplyInfoVO> contentPage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        List<RoleSimplyInfoVO> VOS = roleServiceMapper
                .selectRankRole(contentPage, ContentTypeEnum.ROLE.getType())
                .getRecords();
        return VOS;
    }



}
